﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using XingLucifer.IBase;
using XingLucifer.IBase.Enums;

namespace XingLucifer.Devices.Devices.ElectronicScales
{
    public class AND4531B : IDevices
    {
        private List<byte> _cacheByte = new List<byte>(1024);
        private CancellationTokenSource _tokenSource;
        private ICommunication _com;
        private byte[] _cmd;
        public AND4531B(ICommunication com, CancellationTokenSource tokenSource)
        {
            _com = com;
            _tokenSource = tokenSource;
            _cmd = Encoding.ASCII.GetBytes("Z\r\n");
        }

        public bool WriteSingle(object value, int address, int offset, int length, int count = 3)
        {
            for (int i = 0; i < count; i++)
            {
                try
                {
                    _com.Write(_cmd);
                    return true;
                }
                catch (Exception)
                {
                    if (_tokenSource.Token.IsCancellationRequested)
                    {
                        return false;
                    }
                    _com.ReconnectDisconnection?.Invoke(_com, _com.Index, _com.IP, _com.Port, _com.DeviceType, _com.TaskType, _com.ServiceName, _tokenSource);
                }
            }
            return false;
        }

        public TValue ReadSingle<TValue>(int address = 0, int length = 0, int count = 3)
        {
            byte[] bytes = _cacheByte.ToArray();
            _cacheByte.Clear();
            double? value = GetAndWeight(bytes);
            return value == null ? default : (TValue)(object)value;
        }

        /// <summary>
        /// AND AD 4531B型号电子秤解析
        /// </summary>
        /// <param name="originalbyte"></param>
        /// <returns></returns>
        private double? GetAndWeight(byte[] originalbyte)
        {
            try
            {
                if (originalbyte.Length >= 15)
                {
                    byte[] bytes = new byte[0];
                    var str = Encoding.ASCII.GetString(originalbyte).Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
                    if (str.Length > 1)
                    {
                        int count = 0;
                        for (int i = str.Length - 1; i > 0; i--)
                        {
                            //if (str[i].Length == 13 && str[i].Contains("WT,+"))
                            if (str[i].Length == 13 && str[i].Contains("WT,"))
                            {
                                count = i;
                                break;
                            }
                        }
                        bytes = Encoding.ASCII.GetBytes(str[count]);
                    }
                    else
                    {
                        bytes = Encoding.ASCII.GetBytes(str[0]);
                        if (bytes.Length < 13) return null;
                    }
                    var section1 = Encoding.ASCII.GetString(bytes, 0, 2);//WT
                    var section3 = Encoding.ASCII.GetString(bytes, 3, 1);//+
                    var section4 = Encoding.ASCII.GetString(bytes, 4, 7);//value
                    double.TryParse(section4, out double w);
                    if (section1.ToUpper() == "WT") return w;
                    //if (section1.ToUpper() == "WT" && section3.Contains("+")) return w;
                }
                return null;
            }
            catch (Exception)
            {
                return null;
            }
        }

        public Task Read()
        {
            return Task.Run(() =>
            {
                while (!_tokenSource.Token.IsCancellationRequested)
                {
                    try
                    {
                        _cacheByte.AddRange(_com.Read(20));
                        if (_cacheByte.Count > 1023)
                        {
                            _cacheByte.Clear();
                        }
                        Thread.Sleep(50);
                    }
                    catch (Exception)
                    {
                        _com.ReconnectDisconnection?.Invoke(_com, _com.Index, _com.IP, _com.Port, _com.DeviceType, _com.TaskType, _com.ServiceName, _tokenSource);
                    }
                }
            });
        }

        public bool WriteClass<TClass>(TClass value, int address, int count = 3) where TClass : class
        {
            throw new NotImplementedException("未实现");
        }

        public TClass ReadClass<TClass>(int address, TClass obj = null, int count = 3) where TClass : class
        {
            throw new NotImplementedException("未实现");
        }

        public bool Open() => _com.Open();

        public void Close() => _com.Close();
    }
}
